package com.open.basic.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Supplier;


/**
 * @author: system
 * @Date: 2024/9/14 上午10:16
 * @Version: V1.0
 * @description: ->
 * <pre>
 *   java-线程池+CompletableFuture
 *   https://www.cnblogs.com/dongye95/p/16352895.html
 * </pre>
 */
@Slf4j
public class AsyncContext {

    private static ThreadPoolExecutor asyncPoolExecutor = ThreadPoolUtil.getNewThreadPool("async", 10);

    public static void invokeAsync(Runnable runnable) throws ExecutionException, InterruptedException {
        // 以 Runnable 函数式接口类型为参数，没有返回结果，
        // 异步无返回值 使用自定义线程池
        CompletableFuture.runAsync(runnable, asyncPoolExecutor);
        // 异步无返回值 使用默认线程池 ForkJoinPool.commonPool()
        CompletableFuture.runAsync(runnable);

        // supplyAsync() 以 Supplier 函数式接口类型为参数，返回结果类型为U；Supplier 接口的 get() 是有返回值的(会阻塞)
        CompletableFuture<Object> uCompletableFuture = CompletableFuture.supplyAsync(() -> {
            return null;
        });
        // 阻塞 抛出检查异常
        Object object = uCompletableFuture.get();

        // 阻塞 抛出未经检查的异常
        Object join = uCompletableFuture.join();


        uCompletableFuture.thenApply(param -> {
            return null;
        }).thenApplyAsync(param -> {
            return null;
        });

        CompletableFuture.runAsync(runnable).thenCompose(param -> {
            return null;
        });
    }


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 设置系统属性以指定slf4j.properties文件的位置
        System.setProperty("slf4j.configuration.file", "E:\\CodeProject\\vscodeProject\\codex-a\\codexa\\codex-basic\\src\\main\\resources\\logback-spring.xml");
        int a = 10;
        int b = 20;
        int c = 30;
        log.info("a+b+c={}", a + b + c);

        Runnable runnable = () -> {
            log.info("runnable task: a+b+c={}", a + b + c);
        };

        Supplier<Integer> supplier = () -> {
            log.info("supplier task: a+b+c={}", a + b + c);
            return a + b + c;
        };

        CompletableFuture.runAsync(runnable);

        Void unused = CompletableFuture.runAsync(runnable, asyncPoolExecutor).get();
        log.info("unused:{}", unused);

        int result = CompletableFuture.supplyAsync(supplier).get();
        log.info("result:{}", result);

        Integer i = CompletableFuture.supplyAsync(supplier, asyncPoolExecutor).get();
        log.info("i:{}", i);

        Integer i1 = CompletableFuture.supplyAsync(supplier).thenApply(param -> {
            param = param + 1;
            log.info("param: {}", param);
            return param;
        }).get();
        log.info("i1:{}", i1);

        CompletableFuture.supplyAsync(supplier).thenAcceptAsync(param -> {
            log.info("param: {}", param);
        });
    }

    static Map<String, String> map = new ConcurrentHashMap<>();
    public static void thread1(String key, String value){
        Runnable r = () -> {
            if (map.containsKey(key)){
                return;
            }
            Random random = new Random();
            int i = random.nextInt(1000);
            try {
                Thread.sleep(i);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            map.put(key, value);
        };
        asyncPoolExecutor.execute(r);
    }
}
